import pyglet
from pyglet.gl import *
import game


class Window(pyglet.window.Window):
	
	def __init__(self, fps=40, **kw):
		super(Window, self).__init__(
			config=Config(sample_buffers=1, samples=4, depth_size=24, double_buffer=True),
			**kw)
		self.clear()
		self.flip()
		self.init_graphics()

		self.states = []
		self.queued_states = []
		self.dts = []
		self.fps = fps
		self.max_dt = (1.0/fps) * 10.0
		pyglet.clock.schedule_interval(self.update, 1.0/fps)
	
	def on_resize(self, width, height):
		glViewport(0, 0, width, height)
		glMatrixMode(GL_PROJECTION)
		glLoadIdentity()
		glOrtho(
			-500, 500,
			-500 * height // width, 500 * height // width,
			-1000, # near clip
			1000, # far clip
			)
		glMatrixMode(GL_MODELVIEW)
		glLoadIdentity()
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
	
	def init_graphics(self):
		"""Initialize universal graphics settings"""
		glEnable(GL_BLEND)
		glEnable(GL_POLYGON_OFFSET_FILL)
		glPolygonOffset(1., 1.)
	
	def push_state(self, state):
		"""Push a game state to the top of the stack. This game state
		becomes active on the next update iteration
		"""
		self.queued_states.append(state)
	
	def pop_state(self):
		"""Pop the game state at the top of the stack. The next state
		becomes active. If there are no more states, close the window
		"""
		if self.queued_states:
			self.queued_states.pop()
		else:
			old_state = self.states.pop()
			self.pop_handlers()
			old_state.exit(self)
			if self.states:
				new_state = self.states[-1]
				self.push_handlers(new_state)
				new_state.enter(self)
			else:
				# No more states, we're done
				self.close()
	
	def xon_close(self):
		self.dts = self.dts[3:]
		print '\n'.join(str(x * 1000) for x in self.dts)
		mean = sum(self.dts) / len(self.dts)
		import math
		print 'avg', mean, 'min', min(self.dts), 'max', max(self.dts), 'sdev', math.sqrt(sum((x - mean)**2 for x in self.dts))

	def update(self, dt):
		"""Perform an update iteration and dispatch the on_update event"""
		self.dts.append(dt)
		if self.queued_states:
			if self.states:
				self.pop_handlers()
				self.states[-1].exit(self)
			self.states.extend(self.queued_states)
			self.queued_states = []
			self.push_handlers(self.states[-1])
			self.states[-1].enter(self)
		if dt > self.max_dt:
			dt = self.max_dt # smooth out dt spikes
		game.time += dt
		self.dispatch_event('on_update', dt)

Window.register_event_type('on_update')
